package LinkedList_03.Double_Linked_List_04;

/*
 * @Author 罗
 * @date 2020/3/12 - 6:14 下午
 *
 */

public class DoubleLinkedList <T extends HeroNode>{
    private HeroNode head;
    private HeroNode tail;

    public void reverse(){

        HeroNode current = this.head.getNext();
        HeroNode next = null;
        HeroNode tempHead = new HeroNode(100,"临时头节点");

        while(true){
            if(current.getNext() == null){
                break;
            }
            next = current.getNext();
//            设置取出节点的上一个节点是临时头节点
            current.setPrevious(tempHead);
//            如果头节点有下一个节点
            if(tempHead.getNext() != null ){
//                让头节点的下一个节点指向取出节点
                tempHead.getNext().setPrevious(current);
            }
//            设置取出节点的下一个即诶单是头节点的下一个节点
            current.setNext(tempHead.getNext());

            tempHead.setNext(current);
            current = next;
        }
//        最后将新链表从临时头节点转移到原头节点上
        tempHead.getNext().setPrevious(this.head);
        this.head = tempHead.getNext();

    }

    /*
    * 修改
    * */
    public void update(HeroNode heroNode){
        HeroNode temp = this.head.getNext();
        while (true){
            if(temp == null){
                throw new RuntimeException("未找到，修改失败");
            }
            if(temp.getId() == heroNode.getId()){
                break;
            }
            temp = temp.getNext();
        }
        temp.setName(heroNode.getName());
    }

    public void deleteById(int id){
/*
* 单向链表HeroNode temp = this.head;从头节点开始找是因为，要定位到要删除节点的前一个节点
* 而双向链表直接定位到要删除的节点即可
*
* */
        HeroNode temp = this.head.getNext();
        while(true){

            if(temp == null){
//                已经找到链表最后节点的next
                throw new RuntimeException("未找到该节点");
            }
            if(temp.getId() == id){
                break;
            }
            temp = temp.getNext();
        }
        temp.getPrevious().setNext(temp.getNext());
//        如果删除的是最后一个节点，它之后没有节点，调用setPrevious()会NullPointerException
        if(temp.getNext() != null){
            temp.getNext().setPrevious(temp.getPrevious());
        }
    }
    public void addByOrder(T newNode){
        HeroNode temp = this.head;
        while(true){
/*            本节点之后已经没有元素，说明当前元素就是最后一个元素
                如果跳出while时，temp指向null，则之后的动作会报错
 */
            if(temp.getNext() == null){
                break;
            }
            if(temp.getNext().getId()>newNode.getId()){
//                要添加的位置已找到
                break;
            }else if(temp.getNext().getId() == newNode.getId()){
                throw new RuntimeException("节点重复，添加失败");
            }
            temp = temp.getNext();
        }
//        设置新增节点指向，当前节点的下一个节点
        newNode.setNext(temp.getNext());
//        设置当前节点的下一个节点指向的的上一个节点为 新增节点
//        如果到达末尾，不存在下一个节点，所以不用设置
        if(temp.getNext() != null){
            temp.getNext().setPrevious(newNode);
        }
//        设置新增节点的上一个节点指向本节点
        newNode.setPrevious(temp);
//        设置当前节点的下一个节点是新增节点
        temp.setNext(newNode);
    }




    public void addToTheTail(T node){

        if(tail != null){
            System.out.println("快速插入到尾部");
            tail.setNext(node);
            node.setPrevious(tail);
            tail = node;
            return;
        }

        /*
           不能这样写，HeroNode temp = head.getNext();
           如果这样，若本链表只有头节点，则无法添加元素
        * */
        HeroNode temp = this.head;
        while(true){
//            当后面没有元素相连时，说明到了尽头
            if(temp.getNext() == null){

                break;
            }
            temp = temp.getNext();
        }
        temp.setNext(node);
        node.setPrevious(temp);
        this.tail = node;
    }



    public void show(){
        HeroNode temp = this.head.getNext();
        while(true){
            if(temp == null){
                break;
            }
            System.out.println(temp);
            temp = temp.getNext();
        }
    }

    public <T> DoubleLinkedList() {
        this.head = new HeroNode();
    }
}
